home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1996 April
/
CHIP 1996 aprilis (CD06).zip
/
CHIP_CD06.ISO
/
hypertxt.arj
/
9407
/
LDALL2.CD
< prev
next >
Wrap
Text File
|
1994-11-27
|
13KB
|
246 lines
@VA LOADALL utasítás@N
@Vavagy, a memóriakezelés rejtelmei...@N
Az IBM PC/XT/AT számítógépek memóriakezelése nem éppen
a legjobbak közül való. Valós címzési módban 640
Kbyte hagyományos (DOS-) és 384 Kbyte felsô (upper) memória
címezhetô közvetlenül. A fennmaradó memóriaterületet
alapesetben extendedként könyvelhetjük el, s jobb esetben
programjaink adattárolásra használhatják... Vagy mégsem?
Az alábbiakban egy nem dokumentált utasítást mutatunk be,
amely lehetôvé teszi 80286/80386/80486-os gépeken, hogy
valós címzési módban elérjük a teljes memóriatartományt, s
ott programot is futtassunk. Ez az utasítás a LOADALL. Az
utasítás kódja 80286-os processzoron hexadecimális 0F 05,
míg 80386/80486-os processzoron hexadecimális 0F 07. A
neve arra utal, hogy ezzel az utasítással a processzor
összes regiszterét feltölthetjük.
Az utasítás feladata a processzor úgynevezett cache
regisztereinek gyors inicializálása. Ilyen cache
regiszterek a 80286/80386/80486-os processzorokban
találhatók. Az Intel hivatalos dokumentációjában említést
tesz a cache regiszter felépítésérôl, de hiányosan említi
azokat a regisztereket, amelyeknek van cache regisztere.
Az utasítást, amellyel hozzáférhetnénk ezekhez, nem említi,
sôt tagadja, hogy létezik ilyen. Vajon miért?
@VCache regiszter@N
A cache regiszter a processzor belsô regisztere, amely
három részre van osztva. Sorrendben a szegmenshosszt, a
fizikai szegmens-kezdôcímet, és a hozzáférési byte-ot
tartalmazza.
A fizikai szegmenscím a szegmens fizikai kezdôcímét
határozza meg a memóriában. A szegmenshossz a szegmens
kezdettôl számított hosszát határozza meg byte-okban, míg a
hozzáférési byte a védett módú mûködés során a védelmi
szint információkat tartalmazza. (A cache regiszter
felépítését a kiemelt szövegrészben láthatják.)
Többféle cache regiszter van. Most azonban csak a
szegmensleíró cache regisztereket tartjuk szem elôtt, mivel
a memóriacímzéshez erre van szükségünk. A 80x86-os
architektúrában ismeretesek úgynevezett
szegmensregiszterek, például a CS, a DS, az ES, és az SS.
Mindegyik szegmensregiszternek van saját cache regisztere,
amit a processzor tölt fel értékkel a szegmensregiszter
alapján. Ha például a DS regiszterbe hexadecimális 03F43
értéket töltünk, akkor a hozzá tartozó cache regiszter
fizikai szegmenscím mezôjébe hexadecimális 03F430 érték
kerül. Mivel azonban a szegmensregiszterekbe valós címzési
módban csak maximum hexadecimális 0FFFF érték tölthetô, így
nem tudjuk elérni az @K1 Mbyte+64 Kbyte-16 byte@N feletti
területet. Pontosabban fogalmazva, csak a 8086/80286-os
processzorok nem tudják elérni. A 80386/80486-os
processzorok a 32 bites indexregiszterek (EBX, ESI, EDI
stb.) használatával valós módban is kezelik a teljes
memóriaterületet, példa erre a HIMEM.SYS eszközmeghajtó.
Gondolom, ezek után részletezni sem érdemes, hogy a
80386/80486-os processzoroknál az @KIP@N valós módban is 32
bites, s a használata is lehetséges. Ha a 80286-os
processzornak lenne 32 bites indexregisztere, akkor a
teljes memóriaterület címzésére is képes lenne valós
módban, de mivel nincs... Mivel nincs, marad a LOADALL
utasítás, amellyel közvetlenül a cache regiszter fizikai
szegmenscím mezôjébe tölthetjük a szegmenscímet.
Mivel a cache regiszter valósítja meg a valódi címzést, így
a hozzátartozó szegmensregiszterbe bármilyen érték
tölthetô. A cache regiszterben a következô hozzátartozó
szegmensregiszter hozzáférésig marad a betöltött érték,
azaz, ha a DS szegmensregiszter cache regiszterének fizikai
szegmenscím mezôjébe hexadecimális 200000 értéket töltünk,
akkor a DS regiszter a 2 Mbyte-os címre mutat addig, amíg
például egy @KPOP DS@N utasítás végrehajtásra nem kerül. A
továbbiakban az indexregiszterek segítségével közvetlenül
címezhetjük ezt a területet. Ugyanez igaz a többi, így a CS
szegmensregiszterre is. Megjegyzendô, hogy a megszakítási
vektortábla a szokásos méretû marad, de az @KLIDT@N
utasítással megváltoztathatjuk az elhelyezkedését a
memóriában.
@VGyakorlati alkalmazás@N
A LOADALL utasítás mûködési mechanizmusa mind a három fent
említett processzortípuson azonos, bár a 80286-os
processzorú alkalmazásnál némi technikai különbség van a
80386/80486-hoz képest.
Elsô lépésként egy táblázatot kell létrehoznunk, amely a
regiszterek és cache regiszterek értékeit tartalmazza a
LOADALL utasítás számára. (Lásd @VA 80286 LOADALL esetén@N
@Vkészítendô táblázat felépítése,@N illetve a @VA 80386/80486@N
@VLOADALL esetén készítendô táblázat felépítése@N címû
keretes szövegrészünket!) A táblázat kitöltésénél vigyázni
kell néhány apróságra. Elsôként a gépi státusz szó, a
@KMSW@N vagy @KCR0@N 0. bitjére figyeljünk, mivel ez a
@Kvédett mód@N kapcsoló. Abban az esetben, ha valós módban
szeretnénk használni a LOADALL-t, a 0. bitet 0-ra állítsuk!
A másik fontos regiszter az @KIP@N, amely meghatározza azt
a helyet, ahol a program folytatódik a LOADALL utasítás
végrehajtása után. A @KCS@N regiszterbe töltött érték nem
kerül felhasználásra, mivel a @KCS cache@N regiszter címzi
a kódszegmenst, így ez utóbbit kell helyesen kitölteni. A
többi szegmensregiszterrel ugyanígy ""bánunk el". A
hozzáférési byte-ot mindegyik cache regiszterben
hexadecimális 93-mal kell feltölteni, mert az operációs
rendszer valós módban a 0-s védelmi szinten fut fixen.
Miután elkészült a táblázat, 80286-os esetén át kell
másolni a hexadecimális 0080:0000 címre, mivel a processzor
csak errôl a címrôl tudja betölteni. Az ott elhelyezkedô
adatokat elôtte értelemszerûen el kell menteni.
80386/80486-os processzor esetén a táblázatot nem kell
másolni, a címét egyszerûen be kell tölteni az @KES:EDI@N
regiszterekbe.
Végül végrehajtjuk a LOADALL utasítást, amely a táblázatban
található értékkel tölti fel a hozzájuk tartozó regisztert,
s a program futását a @KCS cache:IP@N címen folytatja, ahol
tulajdonképpen egy speciális alkalmazás helyezkedik el. A
HIMEM.SYS esetében itt történik az extended memória írása,
olvasása egy @KREP MOVSB@N utasítással. Lehetséges más,
teljesen új alkalmazási terület használata is, hiszen ha
védett módba kapcsolunk, a LOADALL segítségével futtahatunk
valós módú programot védett módban, illetve készíthetünk
olyan nyomkövetôt, amely nem foglal egyetlen byte-ot sem a
hagyományos memóriából.
A 80286-os LOADALL használata esetén ügyelni kell a
hexadecimális 0080:0000 címrôl elmentett adatok
visszamásolására, mivel itt néhány ROM BIOS cím található,
melyeket az operációs rendszer használ belépési pontként.
A PC/MS/COMPAQ DOS 3.x verzióinál ezt a helyet üresen
hagyták, így nincs szükség a terület elmentésére illetve
visszamásolására.
A témával kapcsolatos példaprogramot a CT BBS L03
területérôl lehet letölteni.
Végül engedtessék meg néhány gondolat a fentiekkel
kapcsolatban. Nem tudom, kinek mi jut eszébe a fent
leírtak alapján, számomra a tanulság egy szó:
félrevezetés. Erre a vádra az okot a hivatalos
dokumentáció szolgáltatja. Az iAPX 80286/80386/80486
processzorok leírásában külön mesét találtak ki a valós
módú címzésre, s arra, hogy miért nem érik el közvetlenül
az extendednek csúfolt memóriát, és ráadásként több tucat
utasítást sem tesznek közzé. Ez utóbbit valószínûleg
üzleti megfontolásból teszik, saját hasznukra, mellôzve a
felhasználók érdekeit.
@VA cache regiszter felépítése@N
@VA 80286-os cache regiszter felépítése@N
5 -> 1 byte hozzáférési byte
2 -> 3 byte szegmens fizikai kezdôcíme
0 -> 2 byte szegmenshatár
@VA 80386/80486-os cache regiszter felépítése@N
11 -> 1 byte nulla
10 -> 1 byte hozzáférési byte
8 -> 2 byte nulla
4 -> 4 byte szegmens fizikai kezdôcíme (32 bites)
0 -> 4 byte szegmenshatár (32 bit)
@VA 80286 LOADALL esetén készítendô táblázat felépítése@N
0800: 6 N/A (nem hiszem, hiszen pont olyan hosszú, mint egy cache regiszter)
0806: 2 MSW (gépi státusz szó)
0808: 14 N/A (itt vajon mi rejtôzik...)
0816: 2 TR (taszk regiszter) védett mód esetén
0818: 2 FLAGS (flagek)
081a: 2 IP (az új IP)
081c: 2 LDT (lokális leíró tábla regiszter) védett mód esetén
081e: 2 DS
0820: 2 SS
0822: 2 CS
0824: 2 ES
0826: 2 DI
0828: 2 SI
082a: 2 BP
082c: 2 SP
082e: 2 BX
0830: 2 DX
0832: 2 CX
0834: 2 AX
0836: 6 ES cache (ES cache regiszter)
083c: 6 CS cache (CS cache regiszter)
0842: 6 SS cache (SS cache regiszter)
0848: 6 DS cache (DS cache regiszter)
084e: 6 GDTR (globális leíró tábla)
0854: 6 LDT cache (lokális leíró tábla cache) védett mód esetén
085a: 6 IDTR (megszakítási leíró tábla)
0860: 6 TSS cache (taszk szegmens cache) védett mód esetén
@VA 80386/80486 LOADALL esetén készítendô táblázat felépítése@N
Relatív offset Hossz Regiszternév:
0000: 4 CR0 (azonos az MSW regiszterrel)
0004: 4 EFLAGS
0008: 4 EIP
000c: 4 EDI
0010: 4 ESI
0014: 4 EBP
0018: 4 ESP
001c: 4 EBX
0020: 4 EDX
0024: 4 ECX
0028: 4 EAX
002c: 4 DR6
0030: 4 DR7
0034: 4 TR (taszk regiszter)
0038: 4 LDT (lokális leíró tábla regiszter)
003c: 4 GS
0040: 4 FS
0044: 4 DS
0048: 4 SS
004c: 4 CS
0050: 4 ES
0054: 12 TSS (taszk státusz szegmens cache)
0060: 12 IDT (megszakítási leíró tábla cache)
006c: 12 GDT (globális leíró tábla cache)
0078: 12 LDT (lokális leíró tábla cache)
0084: 12 GS cache
0090: 12 FS cache
009c: 12 DS cache
00a8: 12 SS cache
00b4: 12 CS cache
00c0: 12 ES cache
@KDarvas Årpád@N